package com.dyna.cp.redis.service.impl;

import com.dyna.core.exception.CustomException;
import com.dyna.cp.redis.service.DynaRedisService;
import com.dyna.utils.RdsUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class DynaRedisServiceImpl implements DynaRedisService {

    private final StringRedisTemplate stringRedisTemplate;

    @Autowired
    public DynaRedisServiceImpl(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * 通过jmeter测试发现，只有线程数同时请求才会请求失败，如果只用循环，则需要等上一个请求完成才会下一个。
     */
    @Override
    public void lock() {
        Boolean lock = RdsUtil.lock("lock", "123", 3L, TimeUnit.SECONDS);
        log.info("枷锁结果:::{}", lock);
        if (lock) {
            try {
                log.info("业务执行成功");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            } finally {
                log.info("释放锁");
                RdsUtil.unlock("lock");
            }
        } else {
            throw new CustomException("业务繁忙");
        }
    }

    @Override
    public void addBloomFilterData(String filterName, String element) {
        RBloomFilter<Object> bloomFilter = RdsUtil.getBloomFilter(filterName, 1000000L, 0.01);
        bloomFilter.add(element);
    }

    @Override
    public Boolean foundElement(String filterName, String element) {
        RBloomFilter<Object> bloomFilter = RdsUtil.getBloomFilter(filterName, 1000000L, 0.01);
        if (bloomFilter.contains(element)) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

    @Override
    public Boolean initTicket(Integer count) {
        RdsUtil.set("ticket", "10");
        return Boolean.TRUE;
    }

    @Override
    public Long ticket() {
        String script =
                "local key = KEYS[1]    -- 第一个参数是键名\n" +
                        "local decrement = tonumber(ARGV[1])  -- 第二个参数是要减少的数量，默认为1\n" +
                        "\n" +
                        "-- 获取当前点赞数\n" +
                        "local currentLikes = tonumber(redis.call(\"GET\", key))\n" +
                        "\n" +
                        "if currentLikes == nil then\n" +
                        "    -- 如果键不存在，初始化为0\n" +
                        "    redis.call(\"SET\", key, \"0\")\n" +
                        "    return 0\n" +
                        "elseif currentLikes - decrement >= 0 then\n" +
                        "    -- 只有在新的点赞数大于等于0时才进行更新\n" +
                        "    redis.call(\"DECRBY\", key, decrement)\n" +
                        "    return 1\n" +
                        "else\n" +
                        "    -- 如果新的点赞数小于0，则不更新并返回-1表示失败\n" +
                        "    return 2\n" +
                        "end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        List<String> keys = Collections.singletonList("ticket");
        List<String> args = Collections.singletonList(String.valueOf(1));

        Long execute = stringRedisTemplate.execute(redisScript, keys, args.toArray(new String[0]));
        System.out.println(execute);
        return execute;
    }

    @Override
    public Boolean delayMsg(Integer type, String content, long delaySeconds) {
        RdsUtil.addDelayMessage(type, content, delaySeconds);
        return Boolean.TRUE;
    }

    @Override
    public Object script() {
/*        String script = "local key = KEYS[1]\n" +
                "local arg1 = ARGV[1]\n" +
                "if key == 'k1' then\n" +
                "    return 1\n" +
                "elseif key == 'k2' then\n" +
                "    return 2\n" +
                "elseif arg1 == 'test01' then\n" +
                "    return 3\n" +
                "else\n" +
                "    return 0\n" +
                "end";*/
        String script = "return redis.call('GET',  KEYS[1])";

        Object result = RdsUtil.script(
                script,
                Object.class,
                Collections.singletonList("icr:test:2025:04:19"),   // 没有键
                ""     // 作为参数传入
        );

        log.info("result:  {}", result);
        return result;
    }

}